from backend.cews.models import StockItemEDoc
from backend.cews.models import (Log, StockItemTask, StockItem, RepairOrder, RepairOrderImprovementWork, Parts, RepairFitmentLog, RepairOrderPart, RepairOrderPartVersion, RepairOrderPartReplacement, RepairOrderEDoc, StockItemImprovementWork)
from datetime import datetime as DateTime
import json
from django.db.models import Q
from django.db import transaction
import math

def filter_log(log_type, action_type, category_type, stock_code, serial_no,job_order, dateFrom, dateTo, currentPage):
    # LIMIT = 100
    # OFFSET=currentPage * LIMIT
    # print(log_type, action_type, category_type, stock_code, serial_no,job_order, dateFrom, dateTo, currentPage)
    query = Q()
    if log_type:
        query &= Q(log_type=log_type)
        print('1')

    if action_type:
        print('2')
        query &= Q(action_type=action_type)

    if category_type:
        print('3',category_type )
        query &= Q(category_type=category_type)

    if stock_code:
        print('4')
        query &= Q(stock_code=stock_code) | Q(parent_stock_code=stock_code)
       
    if serial_no:
        print('5')
        query &= Q(part=serial_no) | Q(parent_part=serial_no)

    if job_order:
        print('6')
        orders = RepairOrder.objects.filter(deleted=False)
        order = {
            o.order_no : o.id
            for o in orders if o.order_no == job_order
            }
        query &= Q(repair_order=order[job_order])

    if dateFrom and dateTo:
        print('7')
        query &= Q(timestamp__range=[dateFrom, dateTo])

    return Log.objects.filter(query)
    max_page = Log.objects.filter(query).count()/LIMIT
    logs = Log.objects.filter(query).values()
    # print(logs)
    sql_query = str(logs.query)
    if len(logs) > 100:
        logs = logs[OFFSET:OFFSET+LIMIT]

    # print(sql_query)
    return logs, max_page


def get_log_by_log_type(log_type, id):
    def get_log_by_maintenance(log_type, repair_order_id):

        repair_order_parts = RepairOrderPart.objects.filter(repair_order=repair_order_id)
        print('repair_order_parts',repair_order_parts)
        logs = Log.objects.filter(log_type=log_type, repair_order=repair_order_id)

        return logs


    if log_type == 'maintenance':
        logs = get_log_by_maintenance(log_type, id)

    return logs

def create_repair_order_part_fitment_log(child_serial, part_id):

    rfLog = RepairFitmentLog(
        child_serial = child_serial,
        repair_order_part_id = part_id,
    )

    rfLog.save()


def check_description_and_update(log_type, description, data, pk):

    if log_type == Log.LogType.MAINTENANCE:
        return create_maintenance_description(description, data, pk)

    if log_type == Log.LogType.STOCKMASTER:
        return create_stock_master_description(description, data, pk)
    
    if log_type == Log.LogType.PARTMASTER:
        return create_part_master_description(description, data, pk)
   
def create_maintenance_description(description, data, pk):
    if description == 'repair order defitment':
        c = RepairOrderPart.objects.get(pk=data['repair_order_part_id'])
        p = RepairOrderPart.objects.get(pk=c.parent_part.id)
        new_description = f"Order Part:{c.description} defit from Parent Part :{p.description}"

        return {
            "repair_order_id":c.repair_order.id,
            "serial_no": c.serial_no,
            "stock_code": c.stock_code,
            "parent_serial_no": p.serial_no,
            "parent_stock_code": p.stock_code,
            "new_description": new_description
            }
    
    if description == 'repair order fitment':
        c = RepairOrderPart.objects.get(pk=data['repair_order_part_id'])
        p = RepairOrderPart.objects.get(pk=c.parent_part.id)
        new_description = f"Part:{c.description} fit to Parent Part :{p.description}"
        return {
            "repair_order_id":c.repair_order.id,
            "serial_no": c.serial_no,
            "stock_code": c.stock_code,
            "parent_serial_no": p.serial_no,
            "parent_stock_code": p.stock_code,
            "new_description": new_description
            }
    
    if description == 'update repair order part version':

        ropv = RepairOrderPartVersion.objects.get(pk=pk)
        rop = RepairOrderPart.objects.get(pk=ropv.repair_order_part.id)
        p = Parts.objects.get(stock_code=rop.stock_code, serial_no=rop.serial_no, deleted=False)
        result = check_part_is_parent(p)
        if 'sw_ver' in data:
            new_description = f"Order part: {rop.description}, Update S/W version to {data['sw_ver']}"
            
        if 'hw_ver' in data:
            new_description = f"Order part: {rop.description}, Update H/W version to {data['hw_ver']}"

        return {
            "repair_order_id":ropv.repair_order.id,
            "serial_no": result['serial_no'],
            "stock_code": result['stock_code'],
            "parent_serial_no": result['parent_serial_no'],
            "parent_stock_code": result['parent_stock_code'],
            "new_description": new_description
            }
    
    if description == 'create repair order replacement task':
        rop = RepairOrderPart.objects.get(pk=data['repair_order_part_id'])
        p = Parts.objects.get(stock_code=rop.stock_code, serial_no=rop.serial_no)
        result = check_part_is_parent(p)
        new_description = f"Order Part: {rop.description}, Create order replacement: {data['component']}"
        return {
            "repair_order_id":rop.repair_order.id,
            "serial_no": result['serial_no'],
            "stock_code": result['stock_code'],
            "parent_serial_no": result['parent_serial_no'],
            "parent_stock_code": result['parent_stock_code'],
            "new_description": new_description
            }
    
    if description == 'update repair order replacement task':
        print(data)
        ropr = RepairOrderPartReplacement.objects.get(pk=data['repair_order_replacement_id'])
        rop = RepairOrderPart.objects.get(pk=ropr.repair_order_part.id)
        p = Parts.objects.get(stock_code=rop.stock_code, serial_no=rop.serial_no)
        result = check_part_is_parent(p)

        if data['completed'] is True:
            new_description = f"Order Part: {rop.description}, complete order replacement: {ropr.component}"
        else:
            new_description = f"Order Part: {rop.description}, cancel complete order replacement: {ropr.component}"

        return {
            "repair_order_id":ropr.repair_order.id,
            "serial_no": result['serial_no'],
            "stock_code": result['stock_code'],
            "parent_serial_no": result['parent_serial_no'],
            "parent_stock_code": result['parent_stock_code'],
            "new_description": new_description
            }

    if description == 'delete repair order replacement task':
        ropr = RepairOrderPartReplacement.objects.get(pk=data['replacement_task_id'])
        rop = RepairOrderPart.objects.get(pk=ropr.repair_order_part.id)
        p = Parts.objects.get(stock_code=rop.stock_code, serial_no=rop.serial_no)
        result = check_part_is_parent(p)

        new_description = f"Order Part: {rop.description}, delete order replacement: {ropr.component}"

        return {
            "repair_order_id":ropr.repair_order.id,
            "serial_no": result['serial_no'],
            "stock_code": result['stock_code'],
            "parent_serial_no": result['parent_serial_no'],
            "parent_stock_code": result['parent_stock_code'],
            "new_description": new_description
            }
    
    if description == 'update repair order':
        r = RepairOrder.objects.get(pk=pk)
        result = check_part_is_parent(r.primary_part)

        new_description = f"Update repair order: {r.order_no}"

        return {
            "repair_order_id":pk,
            "serial_no": result['serial_no'],
            "stock_code": result['stock_code'],
            "parent_serial_no": result['parent_serial_no'],
            "parent_stock_code": result['parent_stock_code'],
            "new_description": new_description
            }
    
    if description == 'complete repair order edoc':
        roe = RepairOrderEDoc.objects.get(pk=data['id'])

        cancel = ''

        if roe.complete:
            cancel = 'cancel'

        new_description = f"{cancel} complete edoc: {roe.doc_name}"

        return {
            "repair_order_id":roe.repair_order.id,
            "serial_no": roe.serial_no,
            "stock_code": roe.stock_code,
            "parent_serial_no": '',
            "parent_stock_code": '',
            "new_description": new_description
            }
    
    if description == 'complete repair order improvement work':
        roe = RepairOrderImprovementWork.objects.get(pk=data['id'])

        cancel = ''

        if roe.complete:
            cancel = 'cancel'

        new_description = f"{cancel} complete improvement work: {roe.doc_name}"

        return {
            "repair_order_id":roe.repair_order.id,
            "serial_no": roe.serial_no,
            "stock_code": roe.stock_code,
            "parent_serial_no": '',
            "parent_stock_code": '',
            "new_description": new_description
            }
    
    if description == 'complete repair order':
        print(data)
        if data['force'] is True:
            force = 'force'
            
        if data['force'] is False:
            force = ''

        if data['username'] is not None:
            authorized = data['username']
        else:
            authorized = ''

        new_description = f"{authorized} {force} complete the job order"

        return {
            "repair_order_id":data['repair_order_id'],
            "serial_no": '',
            "stock_code": '',
            "parent_serial_no": '',
            "parent_stock_code": '',
            "new_description": new_description
            }
    
def create_stock_master_description(description, data, pk):

    if description == 'update stock item task':
        sit = StockItemTask.objects.get(pk=pk)
        s = StockItem.objects.get(pk=sit.stock_item.id)
        result = check_stock_is_parent(s)
        new_description = f"Stock item, SC: {s.stock_code}, task: {sit.name} is created"

        return {
            "repair_order_id":0,
            "serial_no": '',
            "stock_code": result["stock_code"],
            "parent_serial_no": '',
            "parent_stock_code": result["parent_stock_code"],
            "new_description": new_description
            }

    if description == 'create stock item task':
        s = StockItem.objects.get(pk=data['stock_item'])
        result = check_stock_is_parent(s)
        task_name = data["name"]
        new_description = f"Stock item, SC: {s.stock_code}, task: {task_name} is updated"

        return {
            "repair_order_id":0,
            "serial_no": '',
            "stock_code": result["stock_code"],
            "parent_serial_no": '',
            "parent_stock_code": result["parent_stock_code"],
            "new_description": new_description
            }
    
    if description == 'delete stock item task':
        sit = StockItemTask.objects.get(pk=pk)
        s = StockItem.objects.get(pk=sit.stock_item.id)
        result = check_stock_is_parent(s)
        new_description = f"Stock item, SC: {s.stock_code}, task: {sit.name} is deleted"

        return {
            "repair_order_id":0,
            "serial_no": '',
            "stock_code": result["stock_code"],
            "parent_serial_no": '',
            "parent_stock_code": result["parent_stock_code"],
            "new_description": new_description
            }
    
    if description == 'update stock item edoc':
        sie = StockItemEDoc.objects.get(pk=pk)
        s = StockItem.objects.get(pk=sie.stock_item.id)
        result = check_stock_is_parent(s)
        new_description = f"Stock item, SC: {s.stock_code}, edoc: {sie.doc_name} is updated"

        return {
            "repair_order_id":0,
            "serial_no": '',
            "stock_code": result["stock_code"],
            "parent_serial_no": '',
            "parent_stock_code": result["parent_stock_code"],
            "new_description": new_description
            }
    
    if description == 'update stock item improvement work':
        sii = StockItemImprovementWork.objects.get(pk=pk)
        s = StockItem.objects.get(pk=sii.stock_item.id)
        result = check_stock_is_parent(s)
        new_description = f"Stock item, SC: {s.stock_code}, improvement work: {sii.doc_name} is updated"
        return {
            "repair_order_id":0,
            "serial_no": '',
            "stock_code": result["stock_code"],
            "parent_serial_no": '',
            "parent_stock_code": result["parent_stock_code"],
            "new_description": new_description
            }
    
    if description == 'delete stock item improvement work':
        sii = StockItemImprovementWork.objects.get(pk=pk)
        s = StockItem.objects.get(pk=sii.stock_item.id)
        result = check_stock_is_parent(s)
        new_description = f"Stock item, SC: {s.stock_code}, improvement work: {sii.doc_name} is deleted"
        return {
            "repair_order_id":0,
            "serial_no": '',
            "stock_code": result["stock_code"],
            "parent_serial_no": '',
            "parent_stock_code": result["parent_stock_code"],
            "new_description": new_description
            }
    


def create_part_master_description(description, data, pk):
    if description == 'update part item':
        p = Parts.objects.get(pk=pk)

        result = check_part_is_parent(p)

        new_description = f"Part SC: {p.stock_code}, SN: {p.serial_no} is updated"
        
        return {
            "repair_order_id":0,
            "serial_no": result['serial_no'],
            "stock_code": result['stock_code'],
            "parent_serial_no": result['parent_serial_no'],
            "parent_stock_code": result['parent_stock_code'],
            "new_description": new_description
            }
    
def check_part_is_parent(part):
    parent_serial_no = ''
    parent_stock_code = ''
                
    stock_code = part.stock_code
    serial_no = part.serial_no 

    if part.is_parent:
        parent_serial_no = part.serial_no 
        parent_stock_code = part.stock_code
        stock_code = ''
        serial_no = ''

    return {
        'parent_serial_no':parent_serial_no,
        'parent_stock_code':parent_stock_code,
        'stock_code':stock_code,
        'serial_no':serial_no
    }

def check_stock_is_parent(stock):
    parent_stock_code = ''
                
    stock_code = stock.stock_code

    if stock.is_parent:
        parent_stock_code = stock.stock_code
        stock_code = ''

    return {
        'parent_stock_code':parent_stock_code,
        'stock_code':stock_code,
    }

def get_depot_log_by_part(stock_code, serial_no):
    
    logs = Log.objects.order_by('-id').filter(log_type='depot').filter( Q(stock_code=stock_code,part=serial_no) | Q(parent_stock_code=stock_code, parent_part=serial_no))
    
    return logs

def get_depot_log_by_car(car):
    
    logs = Log.objects.order_by('-id').filter(log_type='depot').filter(description__contains=car)
    
    return logs